package com.online_exam.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.online_exam.domain.ExamPaper;
import com.online_exam.domain.Question;
import com.online_exam.domain.TextContent;
import com.online_exam.domain.User;
import com.online_exam.domain.exam.ExamPaperQuestionItemObject;
import com.online_exam.domain.exam.ExamPaperTitleItemObject;
import com.online_exam.repository.ExamMapper;
import com.online_exam.service.ExamService;
import com.online_exam.service.QuestionService;
import com.online_exam.service.TextContentService;
import com.online_exam.service.UserService;
import com.online_exam.viewmodel.admin.ExamPaper.ExamPaperEditRequestVM;
import com.online_exam.viewmodel.admin.ExamPaper.ExamPaperPageRequestVM;
import com.online_exam.viewmodel.admin.ExamPaper.ExamPaperTitleItemVM;
import com.online_exam.viewmodel.admin.ExamPaper.ExamResponseVM;
import com.online_exam.viewmodel.admin.question.QuestionEditVM;
import com.online_exam.viewmodel.student.dashboard.PaperFilter;
import com.online_exam.viewmodel.student.dashboard.PaperInfo;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
public class ExamServiceImpl implements ExamService {

    @Autowired
    ModelMapper modelMapper;
    @Autowired
    TextContentService textContentService;
    @Autowired
    ExamMapper examMapper;
    @Autowired
    UserService userServicel;
    @Autowired
    QuestionService questionService;

    //转大题vm为大题实体
    List<ExamPaperTitleItemObject> examPaperTitlesFromVM(List<ExamPaperTitleItemVM> vms){
        AtomicInteger index = new AtomicInteger(1);
        return vms.stream().map((p)->{
            //先隐射大题的整体
            ExamPaperTitleItemObject titleItem = modelMapper.map(p, ExamPaperTitleItemObject.class);
            titleItem.setName(p.getName());
            //再映射其中的小题
            List<ExamPaperQuestionItemObject> questionItems = p.getQuestionItems().stream().map(
                    //转vm中的小题为实体中的小题
                    a -> {
                        ExamPaperQuestionItemObject questionItem = new ExamPaperQuestionItemObject();
                        //设置题目id，而不是存储题目内容
                        questionItem.setId(a.getId());
                        //设置题号
                        questionItem.setItemOrder(index.getAndIncrement());
                        return  questionItem;
                    }).collect(Collectors.toList());
            //为大题设置所有小题实体
            titleItem.setQuestionItems(questionItems);
            //返回大题
            return titleItem;
        }).collect(Collectors.toList());
    }


    //设置试卷的总分、题量
    void examPaperEtcFromVM(ExamPaperEditRequestVM vm, ExamPaper examPaper){
        //获取题目总量 -必须mapToInt()才能调用数学方法sum()
        int count = vm.getTitleItems().stream().mapToInt(p -> p.getQuestionItems().size()).sum();
        examPaper.setQuestionCount(count);
        //获取题目总分 -小题必须mapToInt()，大题才能mapToInt()小题，mapToInt()需要明确其中是数字
        int score = vm.getTitleItems().stream().flatMapToInt(q -> q.getQuestionItems().stream().mapToInt(a -> a.getScore())).sum();
        examPaper.setScore(score);
    }

    //转试卷vm为试卷实体
    @Transactional
    public ExamPaper examPaperFromVM(ExamPaperEditRequestVM examVM, User user){
        Date date = new Date();
        //转大题vm为实体
        List<ExamPaperTitleItemObject> examPaperTitleItems = examPaperTitlesFromVM(examVM.getTitleItems());
        //转大题实体为json
        String titleJson = JSON.toJSONString(examPaperTitleItems);
        ExamPaper examPaper;
        //如果id为null则新增，否则为更新
        if (examVM.getId()==null || examVM.getId()==0){
            //初步映射
            examPaper = modelMapper.map(examVM,ExamPaper.class);
            examPaper.setCreateTime(date);
            //插入大题json
            TextContent textContent = new TextContent(titleJson, date);
            textContentService.insertTextContent(textContent);
            examPaper.setFrameTextContentId(textContent.getId());
            examPaper.setCreateUser(user.getId());
            examPaper.setGradeLevel(examVM.getLevel());
            examPaperEtcFromVM(examVM, examPaper);
        //如果是更新
        }else {
            examPaper = examMapper.selectById(examVM.getId());
            modelMapper.map(examVM,examPaper);
            //更新大题json
            TextContent textContent = new TextContent(titleJson, date);
            textContent.setId(examPaper.getFrameTextContentId());
            textContentService.update(textContent);
            examPaper.setGradeLevel(examVM.getLevel());
            examPaperEtcFromVM(examVM, examPaper);
        }
        return examPaper;
    }


    @Override
    public ExamPaperEditRequestVM examPaperToVM(Integer id){
        ExamPaper examPaper = examMapper.selectById(id);
        TextContent textContent = textContentService.selectById(examPaper.getFrameTextContentId());
        List<ExamPaperTitleItemObject> examPaperTitleItemObjects = JSON.parseArray(textContent.getContent(), ExamPaperTitleItemObject.class);
        //先对试卷vm作整体映射
        ExamPaperEditRequestVM examPaperEditRequestVM = modelMapper.map(examPaper, ExamPaperEditRequestVM.class);
        examPaperEditRequestVM.setLevel(examPaper.getGradeLevel());
        //获取大题中所有小题的id
        List<Integer> questionIds = examPaperTitleItemObjects.stream().flatMap(t -> t.getQuestionItems().stream().map(q -> q.getId())).collect(Collectors.toList());
        //根据id集合一次找出所有小题
        List<Question> questions = questionService.selectByIds(questionIds);
        //转大题实体们为VM
        List<ExamPaperTitleItemVM> examPaperTitleItemVMs = examPaperTitleItemObjects.stream().map(t -> {
            //大题整体映射
            ExamPaperTitleItemVM examPaperTitleItemVM = modelMapper.map(t, ExamPaperTitleItemVM.class);
            //对大题中的所有小题进行VM映射
            List<QuestionEditVM> questionEditVMs = t.getQuestionItems().stream().map(q -> {
                //找出id对应的question
                Question question = questions.stream().filter(i -> i.getId().equals(q.getId())).findFirst().get();
                //把question转为VM -包括textContent的映射
                QuestionEditVM questionEditVM = questionService.questionToVM(question);
                questionEditVM.setItemOrder(q.getItemOrder());
                return questionEditVM;
            }).collect(Collectors.toList());
            //为大题设置小题VM
            examPaperTitleItemVM.setQuestionItems(questionEditVMs);
            return examPaperTitleItemVM;
        }).collect(Collectors.toList());
        examPaperEditRequestVM.setTitleItems(examPaperTitleItemVMs);
        return examPaperEditRequestVM;
    }

    @Override
    public Integer update(ExamPaper examPaper) {
        return examMapper.update(examPaper);
    }

    @Override
    public List<PaperInfo> indexPaper(PaperFilter paperFilter) {
        return examMapper.indexVM(paperFilter);
    }


    @Override
    public PageInfo<ExamPaper> page(ExamPaperPageRequestVM model) {
        Page<ExamPaper> page = PageHelper.startPage(model.getPageIndex(), model.getPageSize());
        return page.doSelectPageInfo(()->examMapper.page(model));
    }

    @Override
    public int insert(ExamPaper examPaper) {
        return examMapper.insert(examPaper);
    }
}
